package com.gene.tlonpo.manager;

import java.util.concurrent.TimeUnit;

import com.gene.tlonpo.guard.Guard;
import com.gene.tlonpo.guard.interf.GuardI;
import com.gene.tlonpo.guard.tool.GuardAggregationTool;
import com.gene.tlonpo.manager.interf.GuardManagerI;
import com.gene.tlonpo.manager.type.GuardManageType;
import com.google.common.collect.Lists;
import io.netty.util.HashedWheelTimer;

/**
 * @author gene
 * 超时管理器
 * 采用轮盘算法，100ms检查一次，所以会有100ms左右的误差，可接受
 * 单例
 */
public class TimeOutManager implements GuardManagerI {

    public static final TimeOutManager INSTANCE = new TimeOutManager();

    private static HashedWheelTimer timer = new HashedWheelTimer(100, TimeUnit.MILLISECONDS);

    private TimeOutManager() {
    }

    /**
     * 添加进超时管理
     * 1.如果超时，以guardId的维度移除本地的guard
     * 2.超时先检查本地是否存在，如果已经不存在，说明本guard已经进行过业务处理，不在callback
     * 3.分布式的guard不适合在此处进行移除。因为，分布式的guard维度是host+port的维度，直接删除会存在误删的情况
     * @param guardI
     */
    @Override
    public void addGuard(GuardI guardI) {
        if (!(guardI instanceof Guard)) {
            throw new RuntimeException(
                    "can not execute timeoutmanager,because of param type is not com.gene.tlonpo.guard.Guard");
        }
        Guard guard = (Guard) guardI;

        //加入超时管理策略
        timer.newTimeout(timeout -> {

            //如果不
            GuardI guard1 = GuardAggregationTool.getGuard(guard.getBizKey(), guard.getGuardId(), GuardManageType.LOCAL);
            if (guard1 == null) {
                return;
            }

            //移除本地哨兵管理器管理的本哨兵信息
            GuardAggregationTool.removeGuard(guard, GuardManageType.LOCAL);

            //通知
            Object callbackData = guard.getCallBack().callback(guard.getCallBackReq());
            guard.getAsynContext().write(callbackData);
        }, guard.getTimeOut(), guard.getTimeOutUnit());

    }
}
